﻿using System;
using System.Collections;
using System.Threading;
using System.Text;

using GameServer.Networking;
using GameServer.Networking.Packets;
using GameServer.Virtual_Objects.User;

using System.Net;

namespace GameServer.Managers
{
    class UserManager
    {
        private static Thread _pingThread = null;
        private static ArrayList _Users = new ArrayList();
        //private static Hashtable _Users = new Hashtable(9999999);

        public static void setup()
        {
            _pingThread = new Thread(new ThreadStart(pingThread));
            _pingThread.Priority = ThreadPriority.AboveNormal;
            _pingThread.Start();
        }

        ~UserManager()
        {
       
        }

        private static void pingThread()
        {
            while (true)
            {
                try
                {
                    foreach (virtualUser User in _Users)
                    {
                        if (User.pingOK)
                        {
                            try
                            {
                                byte[] buffer = new byte[32];
                                System.Net.NetworkInformation.PingOptions pingOptions = new System.Net.NetworkInformation.PingOptions(128, true);
                                System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
                                System.Net.NetworkInformation.PingReply pingReply = ping.Send(((IPEndPoint)User.uSocket.RemoteEndPoint).Address, 75, buffer, pingOptions);

                                if (pingReply != null)
                                {
                                    switch (pingReply.Status)
                                    {
                                        case System.Net.NetworkInformation.IPStatus.Success:
                                            User.Ping = pingReply.RoundtripTime;
                                            break;
                                    }
                                }
                            }
                            catch
                            {
                            }
                            User.pingOK = false;
                            User.send(new PACKET_PING(User));
                        }
                    }
                }
                catch { }
                Thread.Sleep(2500);
            }
        }

        public static ArrayList getAllUsers()
        {
            return new ArrayList(_Users);
        }

        public static ArrayList get50Players()
        {
            ArrayList players = getAllUsers();
            if (players.Count >= 50)
                return players.GetRange(0, 50);
            else
                return players;
        }

        public static virtualUser getUser(int ID)
        {
            foreach (virtualUser ServerUser in getAllUsers())
            {
                if (ServerUser.UserID == ID)
                    return ServerUser;
            }
            /*
            if (_Users.Contains(ID))
            {
                return (virtualUser)_Users[ID];
            }
            */
            return null;
        }

        public static virtualUser getUserBySessionID(int SessionID)
        {
            virtualUser Target = null;
            foreach (virtualUser User in _Users)
            {
                if (User.SessionID == SessionID)
                return Target = User;
            }
            return null;
        }

        public static virtualUser getUser(string Username)
        {
            foreach (virtualUser User in _Users)
            {
                if (User.Nickname.ToLower() == Username.ToLower())
                {
                    return User;
                }
            }

            return null;
        }

        public static virtualUser getTargetUser(int SessionID)
        {
            foreach (virtualUser User in _Users)
            {
                if (User.SessionID == SessionID)
                    return User;
            }

            return null;
        }

        public static bool addUser(virtualUser User)
        {
            if (_Users.Contains(User) == false)
            {
                _Users.Add(User);
                DB.runQuery("UPDATE users SET online = '1' WHERE id=" + User.UserID);

                Log.WriteLine(User.Nickname + " logged in!");

                return true;
            }
            return false;
        }

        public static bool removeUser(virtualUser User)
        {
            if (_Users.Contains(User))
            {
                _Users.Remove(User);
                Log.WriteLine(User.Nickname + " logged out.");
                DB.runQuery("UPDATE users SET online='0', kills='" + User.Kills + "',deaths='" + User.Deaths + "', exp='" + User.Exp + "', dinar='" + User.Dinar + "' WHERE id=" + User.UserID);
                return true;
            }

            return false;
        }

        public static ArrayList getUsersInChannel(int ChannelID, bool inRoom)
        {
            ArrayList Users = new ArrayList();
            foreach (virtualUser User in _Users)
            {
                if (User.Channel == ChannelID)
                {
                    if (inRoom == false & User.Room != null) continue;

                    Users.Add(User);
                }
            }

            return Users;
        }
        
        public static void sendToServer(Packet p)
        {
            foreach (virtualUser ServerUser in _Users)
            {
                ServerUser.send(p);
            }
        }

        public static void refreshRoom(Virtual_Objects.Room.virtualRoom Room)
        {
            foreach (Virtual_Objects.User.virtualUser _User in UserManager.getUsersInChannel(Room.Channel, false))
            {
                if (_User.Page == Math.Floor(Convert.ToDecimal(Room.ID / 14)))
                {
                    _User.send(new PACKET_ROOM_UPDATE(Room));
                }
            }
        }

        public static void sendToChannel(int Channel, bool inRoom, Packet p)
        {
            foreach (virtualUser User in _Users)
            {
                if (User.Channel == Channel)
                {
                    if (User.Room != null && !inRoom) continue;
                    User.send(p);
                    User.send(new PACKET_ROOM_LIST(User, 0));
                }
            }
        }

        public static int UserCount
        {
            get
            {
                return _Users.Count;
            }
        }
    }
}